
#ifndef __GAME_SERVER_H__
#define __GAME_SERVER_H__

class ClientThread;

// =========================================================
// Game Server Class (Singleton)
// =========================================================

class GameServer {

public:

	// == Public Methods ==

	static inline GameServer * instance(void)
	{
		if (_instance == 0)
			_instance = new GameServer;

		return (_instance);
	}

	static inline void kill(void)
	{
		if (_instance != 0)
		{
			delete _instance;
			_instance = 0;
		}
	}

	bool isGameRunning(void) const { return (_gameStats == PLAYER_IN_GAME); };

	// Start The Server And Load Preferences From A Configuration File.
	bool init(const char * cfgFile);

	// Wait For Players To Connect Until Max Connections Is Reached.
	void waitForConnections(int maxConnections = 2);

	// Runs The Game Logic.
	void startGame(void);

	// Reset The Game.
	void resetGame(void);

	// Actually Tests If The Player Won, Lost Or Draw The Game.
	// Returns The New Player Flags.
	int checkMyGameState(char player);

	// Allow Synchronized Read Only Access To The Board.
	void readBoard(char buff[BOARD_ROWS][BOARD_COLS]) const;
	void readBoardElement(char & elem, int row, int col) const;

	// Allow Synchronized Write Only Access To The Board.
	void writeBoard(const char buff[BOARD_ROWS][BOARD_COLS]);
	void writeBoardElement(char elem, int row, int col);

	// Player symbols ['X', 'O'].
	static const char SymbolTable[2];

private:

	// == Private Methods ==

	GameServer(void);
	~GameServer(void);

private:

	// == Private Data ==

	static GameServer * _instance;

	SocketServer * _socket;

	// Game Related Data:

	int _gameStats;

	// The Tic Tac Toe Board. This Data Is Sent To All Players Once Changed.
	char _gameBoard[BOARD_ROWS][BOARD_COLS];

	// Mutex Object, To Sync The Threads.
	Mutex _mtx;

	// Connected Clients.
	std::vector<ClientThread *> _clientThreads;
};

// =========================================================
// Client Thread Class
// =========================================================

class ClientThread {

public:

	// == Public Methods ==

	ClientThread(void);

	ClientThread(Socket * sock, char symbol, int flags);

	static void threadProc(void * param);

	void setPlayerFlags(int flags);

	void begin();

	~ClientThread(void);

	// Data Access Methods:
	int getPlayerFlags(void) const;
	char getPlayerSymbol(void) const;
	const Socket * getSocketPtr(void) const;

private:

	// == Private Data ==

	Socket * _socket;

	// Symbol This Player Is Using. ie: X or O
	char _symbol;

	// Static symbol that stores the last player that made a move
	static char globalSymbol;

	// Misc Flags Related To The Game.
	int _playerFlags;

	// Signals to the player thread to terminate.
	char _terminate_thread_flag;

	Thread * _t;
};

#endif // __GAME_SERVER_H__
